// Loader.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

#include "ApplicationsConfig.h"
#include "OutputConfig.h"
#include "ProcessInfo.h"
#include "FileSystem.h"


#ifdef _MANAGED
#pragma managed(push, off)
#endif


static HMODULE hmAbpa = NULL;


// NOTE: a path to this loader must be specified in
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs
// registry key

bool enoughDiskSpace(void) {
	// NOTE: we don't want to link with additional
	/// resources, required by "OutputConfig", so copy-paste
	// is allowed here
	platform::XString location;
	platform::RegistryHelper::RegistryKey key(platform::RegistryHelper::RK_ABPA_BASE, REGISTRY_ROOT_KEY);
	key.getStringValue(REGISTRY_VALUE_LOCATION, location);

	platform::FileSystem::SizeLimit limit(location, platform::FileSystem::SizeLimit::SLT_FREE_SIZE_MB, (4 * 1024 /*4GB*/));
	return !limit.isOverLimit();
}

bool shouldAttachToCurrentProcess(void) {
	platform::XString name;
	platform::ProcessInfo::GetCurrentProcessExeName(name);

	config::ApplicationsConfig confApp;
	return (confApp.shouldAttachToApplication(name) && enoughDiskSpace());
}


// This finction should be called only if we want to
// monitor current process, and it will load the 
// engine
void loadAbpa(void) {
	hmAbpa = ::LoadLibrary(_T("ABPAEngine"));
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		if (!shouldAttachToCurrentProcess())
			return TRUE;
		
		loadAbpa();
		break;

	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		break;

	case DLL_PROCESS_DETACH:
		if (hmAbpa != NULL)
			::FreeLibrary(hmAbpa);

		break;
	}
	return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

